/*
 * @Author       : Atonidas
 * @LastEditors  : error: git config user.name & please set dead value or install git
 * @LastEditTime : 2023-10-05 15:14:01
 * @FilePath     : \multiplex_controller\User\User\user.c
 * @Description  : 项目中的用户函数，主要为不通用的交互菜单等代码
 */

#include "Encoder\Encoder.h"
#include "OLED\oled.h"
#include "User\user.h"
#include "tim.h"
#include "HC595\hc595.h"

#define NUM_CHANNELS  8
#define HOLD_TIME_MAX 2500 // 长按时间最大值
#define HOLD_TIME_MIN 1500 // 长按时间最小值

// 记录器数据结构体
typedef struct {
    uint16_t pin;     // 具体的引脚号
    int timerValue;   // 存放引脚的计数器值
    int successCount; // 成功次数
    int failureCount; // 失败次数
} GPIO_CHANNEL;

GPIO_CHANNEL channels[NUM_CHANNELS] = {
    {CH0_Pin, 0, 0, 0},
    {CH1_Pin, 0, 0, 0},
    {CH2_Pin, 0, 0, 0},
    {CH3_Pin, 0, 0, 0},
    {CH4_Pin, 0, 0, 0},
    {CH5_Pin, 0, 0, 0},
    {CH6_Pin, 0, 0, 0},
    {CH7_Pin, 0, 0, 0},
};

// 记录状态枚举
enum eRecordState {
    Record_Wait = 0,
    Record_Work,
};

/**
 * @description: 用户主服务函数，用于UI初始化及主要参数显示界面（//TODO:）
 * @param parameter 线程入口参数，默认无
 * @return
 */
void userApp_thread_entry(void *parameter)
{
    rt_thread_mdelay(500);
    OLED_Init();
    OLED_Clear_Screen(0x00);

    for (uint8_t i = 1; i < numEncoders; i += 2) { // 开机显示已有参数信息
        OLED_FillArea(0, 16, SCREEN_W, 32, 0);
        OLED_ShowString(0, 0, encoder_services[i].name, 15, 0);
        OLED_ShowNumber(0, 16, getEncoderValue(i), 3, 15, 0);
        OLED_ShowString(0, 32, encoder_services[i + 1].name, 15, 0);
        OLED_ShowNumber(0, 48, getEncoderValue(i + 1), 3, 15, 0);
        rt_thread_mdelay(500);
    }
    Main_Dispaly();

    for (;;) {
        HC595_WriteByte(0xFF);
        rt_thread_mdelay(2000);
        HC595_WriteByte(0x00);
        rt_thread_mdelay(2000);
    }
}

static uint8_t Record_State = Record_Wait;
void UpdateRecordState(void)
{
    static uint16_t Record_Timer = 0;
    if (Record_State == Record_Work) {
        Record_Timer++;
    }
    if (Record_Timer >= 50) // 5s
    {
        Record_State = Record_Wait;
        HAL_TIM_Base_Stop(&htim16);
        __HAL_TIM_SetCounter(&htim16, 0);
    }
}

uint16_t readTimerValue(void)
{
    return __HAL_TIM_GetCounter(&htim16);
}

void UpdateRecorder(uint16_t GPIO_Pin, uint8_t mode)
{
    GPIO_CHANNEL *channel = NULL;
    for (int i = 0; i < NUM_CHANNELS; i++) {   // 遍历通道数组
        if (channels[i].pin == GPIO_Pin) {     // 查找匹配的通道
            if (Record_State == Record_Wait) { // 如果记录状态为等待状态，表示第一次触发记录
                Record_State = Record_Work;    // 修改记录状态为工作状态
                HAL_TIM_Base_Start(&htim16);   // 启动定时器
            }
            channel = &channels[i]; // 将匹配的通道赋值给指针变量
            break;                  // 跳出循环
        }
    }
    if (channel != NULL) {                                         // 如果通道不为空
        if (mode == CHANNEL_START) {                               // 如果模式为 0，表示读取定时器值
            channel->timerValue = readTimerValue();                // 将定时器的值保存到通道结构体中
        } else if (mode == CHANNEL_END) {                          // 如果模式为 1，表示检测按键释放状态
            int timeDiff = readTimerValue() - channel->timerValue; // 计算时间差
                                                                   // 检查时间差是否在指定范围内
            if (timeDiff >= HOLD_TIME_MIN && timeDiff <= HOLD_TIME_MAX) {
                channel->successCount++; // 更新成功次数
            } else {
                channel->failureCount++; // 更新失败次数
            }
        }
    } // 读取定时器值
}

void Encoder_MainMenu(void)
{
    OLED_FillArea(0, 16, SCREEN_W, 32, 0);
    OLED_ShowString(0, 16, encoder_services[getEncoderValue(0)].name, 15, 0);
}